package com.ssm.subject.application.controller;

import com.alibaba.fastjson.JSON;
import com.google.common.base.Preconditions;
import com.ssm.subject.application.convert.SubjectCategoryDTOConvert;
import com.ssm.subject.application.convert.SubjectLabelDTOConvert;
import com.ssm.subject.application.dto.SubjectCategoryDTO;
import com.ssm.subject.application.dto.SubjectLabelDTO;

import com.ssm.subject.common.entity.Result;
import com.ssm.subject.common.util.LoginUtil;
import com.ssm.subject.domain.bo.SubjectCategoryBO;
import com.ssm.subject.domain.convert.SubjectCategoryBOConverter;
import com.ssm.subject.domain.service.SubjectCategoryDomainService;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.lang.StringUtils;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import java.util.LinkedList;
import java.util.List;

/**
 * 刷题分类controller
 */
@RestController
@RequestMapping("/subject/category")
@Log4j2
public class SubjectCategoryController {
    @Resource
    private SubjectCategoryDomainService subjectCategoryDomainService;

    /**
     * 新增分类
     * @param subjectCategoryDto
     * @return
     */
    @PostMapping("/add")
    public Result<Boolean> add(@RequestBody SubjectCategoryDTO subjectCategoryDto) {
        try {
            //高并发下，会先把json序列号执行一次，即使系统日志级别为debug，info级别的日志不输出但也要做一次序列化转化，耗性能
            if(log.isInfoEnabled()) { //判断系统日志级别是否为info，返回值true，再执行日志操作。
                log.info("SubjectCategoryController.add.dto:{}", JSON.toJSONString(subjectCategoryDto));
            }

            //参数校验不满足时，异常值为errorMessage；checkNotNull参数为Object类型 checkArgument参数为Boolean类型false则报错
            Preconditions.checkNotNull(subjectCategoryDto.getCategoryType(), "分类类型不能为空");
            Preconditions.checkArgument(StringUtils.isNotBlank(subjectCategoryDto.getCategoryName()), "分类名称不能为空");
            Preconditions.checkNotNull(subjectCategoryDto.getParentId(), "分类父级id不能为空");

            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConvert.INSTANCE.categoryDtoToBo(subjectCategoryDto);
            Boolean result = subjectCategoryDomainService.add(subjectCategoryBO) > 0;
            return Result.ok(result);
        } catch (Exception e) {
            log.info("SubjectCategoryController.add.error:{}", e.getMessage(), e);
            return Result.fail("新增分类失败"); //获取自定义异常值
        }
    }

    /**
     * 查询大分类(根据参数中的type来判断大小分类)
     * @return
     */
    @PostMapping("/queryPrimaryCategory")
    public Result<List<SubjectCategoryDTO>> queryPrimaryCategory(@RequestBody SubjectCategoryDTO subjectCategoryDto) {
        try {
            System.out.println(LoginUtil.getLoginId());
            Preconditions.checkNotNull(subjectCategoryDto.getCategoryType(), "分类类型不能为空");
            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConvert.INSTANCE.categoryDtoToBo(subjectCategoryDto);
            List<SubjectCategoryBO> subjectCategoryBOList = subjectCategoryDomainService.queryCategory(subjectCategoryBO);
            List<SubjectCategoryDTO> subjectCategoryDTOS = SubjectCategoryDTOConvert.INSTANCE.categoryBoListToDtoList(subjectCategoryBOList);
            if(log.isInfoEnabled()) {
                log.info("SubjectCategoryController.queryCategory.subjectCategoryDtolist:{}", JSON.toJSONString(subjectCategoryDTOS));
            }
            return Result.ok(subjectCategoryDTOS);
        } catch (Exception e) {
            log.info("SubjectCategoryController.queryCategory.error:{}", e.getMessage(), e);
            return Result.fail("查询大分类失败");
        }
    }

    /**
     * 查询大分类下的小分类
     * @param subjectCategoryDto 查询小分类需要动态的父级id
     * @return
     */
    @PostMapping("/queryCategoryByPrimary")
    public Result<List<SubjectCategoryDTO>> queryCategoryByPrimary(@RequestBody SubjectCategoryDTO subjectCategoryDto) {
        try {
            Preconditions.checkNotNull(subjectCategoryDto.getCategoryType(), "分类类型不能为空");
            Preconditions.checkNotNull(subjectCategoryDto.getParentId(), "父级id不能为空");
            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConvert.INSTANCE.categoryDtoToBo(subjectCategoryDto);
            List<SubjectCategoryBO> subjectCategoryBOList = subjectCategoryDomainService.queryCategory(subjectCategoryBO);
            List<SubjectCategoryDTO> subjectCategoryDTOS = SubjectCategoryDTOConvert.INSTANCE.categoryBoListToDtoList(subjectCategoryBOList);
            if(log.isInfoEnabled()) {
                log.info("SubjectCategoryController.queryCategory.subjectCategoryDtolist:{}", JSON.toJSONString(subjectCategoryDTOS));
            }
            return Result.ok(subjectCategoryDTOS);
        } catch (Exception e) {
            log.info("SubjectCategoryController.queryCategory.error:{}", e.getMessage(), e);
            return Result.fail("查询小分类失败");
        }
    }

    /**
     * 修改题目分类
     * @param subjectCategoryDto
     * @return
     */
    @PostMapping("/update")
    public Result<Boolean> update(@RequestBody SubjectCategoryDTO subjectCategoryDto) {
        try {
            if(log.isInfoEnabled()) {
                log.info("SubjectCategoryController.update.subjectCategoryDto:{}", subjectCategoryDto);
            }

            Preconditions.checkNotNull(subjectCategoryDto.getId(), "id不能为空");

            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConvert.INSTANCE.categoryDtoToBo(subjectCategoryDto);
            Boolean result = subjectCategoryDomainService.update(subjectCategoryBO) > 0;
            return Result.ok(result);
        } catch (Exception e) {
            log.info("SubjectCategoryController.update.error:{}", e.getMessage(), e);
            return Result.fail("修改分类失败");
        }
    }

    /**
     * 删除题目分类(逻辑删除本质是修改is_deleted字段，domain层调用update方法)
     * @param subjectCategoryDto
     * @return
     */
    @PostMapping("/delete")
    public Result<Boolean> delete(@RequestBody SubjectCategoryDTO subjectCategoryDto) {
        try {
            if(log.isInfoEnabled()) {
                log.info("SubjectCategoryController.delete.subjectCategoryDto:{}", subjectCategoryDto);
            }
            Preconditions.checkNotNull(subjectCategoryDto.getId(), "id不能为空");
            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConvert.INSTANCE.categoryDtoToBo(subjectCategoryDto);
            Boolean result = subjectCategoryDomainService.delete(subjectCategoryBO) > 0;
            return Result.ok(result);
        } catch (Exception e) {
            log.info("SubjectCategoryController.delete.error:{}", e.getMessage(), e);
            return Result.fail("删除分类失败");
        }
    }

    /**
     * 查询分类及标签一次性
     * @param subjectCategoryDTO: 传入大分类id进行查询
     * 在首页想要获取大分类下的所有小分类及对应标签，需要查询大分类下的小分类，再根据每个小分类查询对应的标签。
     * 此处进行接口统一返回，否则需要前端轮询调用之前的查询接口。
     */
    @PostMapping("/queryCategoryAndLabel")
    public Result<List<SubjectCategoryDTO>> queryCategoryAndLabel(@RequestBody SubjectCategoryDTO subjectCategoryDTO) {
        try {
            if(log.isInfoEnabled()) {
                log.info("SubjectCategoryController.queryCategoryAndLabel.dto:{}", JSON.toJSONString(subjectCategoryDTO));
            }
            Preconditions.checkNotNull(subjectCategoryDTO.getId(), "分类id不能为空");
            SubjectCategoryBO subjectCategoryBO = SubjectCategoryDTOConvert.INSTANCE.categoryDtoToBo(subjectCategoryDTO);
            List<SubjectCategoryBO> subjectCategoryBOList = subjectCategoryDomainService.queryCategoryAndLabel(subjectCategoryBO);
            //相同属性才能转，标签List里面的DTO和BO不一样，mapstruct转不了
            List<SubjectCategoryDTO> subjectCategoryDTOS = new LinkedList<>();
            if(!CollectionUtils.isEmpty(subjectCategoryBOList)) {
                subjectCategoryBOList.forEach(bo -> {
                    SubjectCategoryDTO dto = SubjectCategoryDTOConvert.INSTANCE.categoryBoToDto(bo);
                    List<SubjectLabelDTO> subjectLabelDTOS = SubjectLabelDTOConvert.INSTANCE.SubjectLabeBosToDtos(bo.getLabelBOList());
                    dto.setLabelDTOList(subjectLabelDTOS);
                    subjectCategoryDTOS.add(dto);
                });
            }
            return Result.ok(subjectCategoryDTOS);
        } catch (Exception e) {
            log.info("SubjectCategoryController.queryCategoryAndLabel.error:{}", e.getMessage(), e);
            return Result.fail("一次性查询分类及标签失败");
        }
    }
}
